home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / ms-0_06.lha / mslaved-0.06 / mslavedc.c < prev    next >
C/C++ Source or Header  |  1991-07-30  |  7KB  |  269 lines

  1. /* mslavedc.c - MandelSpawn computation server control program */
  2. /* (named in accordance with timedc, etc.). */
  3.  
  4. /*  This file is part of MandelSpawn, a parallel Mandelbrot program for
  5.     the X window system.
  6.  
  7.     Copyright (C) 1990 Andreas Gustafsson
  8.  
  9.     MandelSpawn is free software; you can redistribute it and/or modify
  10.     it under the terms of the GNU General Public License, version 1,
  11.     as published by the Free Software Foundation.
  12.  
  13.     MandelSpawn is distributed in the hope that it will be useful,
  14.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.     GNU General Public License for more details.
  17.  
  18.     You should have received a copy of the GNU General Public License,
  19.     version 1, along with this program; if not, write to the Free 
  20.     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. */
  22.  
  23. #include <stdio.h>
  24. #include <errno.h>
  25. #include <fcntl.h>
  26. #include <sys/ioctl.h>
  27. #include <signal.h>
  28.  
  29. /* The only system I know needs these is SCO Unix, which needs them to */
  30. /* define FNDELAY.  If they cause trouble with you system, remove them */
  31. #include <sys/types.h>
  32. #include <sys/file.h>
  33.  
  34. #include "ms_ipc.h"
  35.  
  36. #define RETRIES 5 /* how many times to retry getting a PID in ping() */
  37.  
  38. extern int errno; /* 4.3BSD needs this even when errno.h is included */
  39.  
  40. char *me;         /* name of program */
  41. int port=DEFAULT_PORT;    /* UDP port */
  42. char *command=NULL;
  43. char *timeout_arg="-t900"; /* by default time out in 15 minutes */
  44. char *nice_arg=NULL;
  45. int kill_mode=0;
  46.  
  47.  
  48. /* report a fatal error and exit */
  49.  
  50. error(s)
  51.      char *s;
  52. { fprintf(stderr, "%s: ", me);
  53.   perror(s);
  54.   exit(1);
  55. }
  56.  
  57.  
  58. /* Repeatedly send datagrams to "host" trying to find out the pid of */
  59. /* the existing server, if any.  Returns the pid or 0 if no response. */
  60.  
  61. int ping(host)
  62.      char *host;
  63. { int i;
  64.   int status;
  65.   WhoAreYouMessage out;
  66.   Message in;
  67.   int osock, isock;
  68.   struct sockaddr_in oname, iname, mname;
  69.   int mnamelen;
  70.   struct hostent *hp, *gethostbyname();
  71.   /* set up the output socket; use an arbitrary port */
  72.   osock=socket(AF_INET, SOCK_DGRAM, 0);
  73.   if(osock<0)
  74.   { error("opening output socket");
  75.   }
  76.   hp=gethostbyname(host);
  77.   if(hp==0)
  78.   { error("unknown host");
  79.   }
  80.   /* set up the destination address */
  81.   oname.sin_family=AF_INET;
  82.   oname.sin_port=htons(port);
  83.   bcopy(hp->h_addr, (char *)&oname.sin_addr, hp->h_length);
  84.   isock=socket(AF_INET, SOCK_DGRAM, 0);
  85.   if(isock<0)
  86.   { error("opening input socket");
  87.   }
  88.   iname.sin_family=AF_INET;
  89.   iname.sin_addr.s_addr=INADDR_ANY;
  90.   iname.sin_port=0;
  91.   if(bind(isock, &iname, (int) sizeof(iname)))
  92.   { error("binding input socket");
  93.   }
  94.   if(fcntl(isock, F_SETFL, FNDELAY) == -1)
  95.   { error("unblocking socket");
  96.   }
  97.   mnamelen=sizeof(mname);
  98.   if(getsockname(isock, &mname, &mnamelen)== -1)
  99.     error("getsockname");
  100.   out.header.magic=htons(MAGIC);
  101.   out.header.version=htons(VERSION);
  102.   out.header.type=htons(WHO_R_U_MESSAGE);
  103.   out.port=mname.sin_port; /* in network byte order already */
  104.   for(i=0; i<RETRIES; i++)
  105.   { int nbytes;
  106.     int fromlen;
  107.     if(sendto(osock, (char *)&out, sizeof(WhoAreYouMessage), 0,
  108.           (struct sockaddr *)&oname, sizeof(oname)) < 0)
  109.       error("sending pid inquiry message");
  110.     /* This previously used read(), but some non-BSD TCP/IP implementations */
  111.     /* don't allow it to be used with connectionless sockets.  Also, */
  112.     /* while the Sun implementation does allow for a null pointer */
  113.     /* for the "from" argument in recvfrom(), the "fromlen" argument */
  114.     /* may not be a null pointer. */
  115.     nbytes = recvfrom(isock, (char *) &in, sizeof(in),
  116.               0, (struct sockaddr *) 0, &fromlen);
  117.       if(nbytes == 0
  118. #ifdef EWOULDBLOCK
  119.      || (nbytes == -1 && errno == EWOULDBLOCK)
  120. #endif
  121.     )
  122.       {    /* no reply yet */
  123.     sleep(1);
  124.       }
  125.       else if(nbytes == -1)
  126.       {    error("receiving pid info");
  127.       }
  128.       else /* got a reply */
  129.       {    status=ntohs(in.iam.pid);
  130.     goto done;
  131.       }
  132.   }
  133.   status=0; /* unsuccessful */
  134.  done:
  135.   (void) close(osock);
  136.   (void) close(isock);
  137.   return(status);
  138. }
  139.  
  140.  
  141. /* Kill any server that is already active in this machine */
  142. /* return 0 if successful kill, 1 if no response */
  143. int murder()
  144. { int pid;
  145.   char my_name[256];
  146.   if(gethostname(my_name, sizeof(my_name)) == 1)
  147.     error("gethostname");
  148.   pid=ping(my_name); /* get pid of existing server, if any */
  149.   if(pid==0)
  150.     return(1); /* return failed exit status */
  151.   if(kill(pid, SIGTERM)== -1) 
  152.     error("kill");
  153.   return(0);
  154. }
  155.  
  156.  
  157. /* Set up the file handles and exec an mslaved */
  158.  
  159. void birth()
  160. { int isock;
  161.   struct sockaddr_in iname;
  162.   int tty;
  163.   int i;
  164.  
  165.   /* argument list for mslaved */
  166.   char *arglist[10]; /* more than enough */
  167.   char **a; /* pointer to the above */
  168.  
  169.   /* set up the socket */
  170.   isock=socket(AF_INET, SOCK_DGRAM, 0);
  171.   if(isock<0)
  172.   { error("opening socket");
  173.   }
  174.   iname.sin_family=AF_INET;
  175.   iname.sin_addr.s_addr=INADDR_ANY;
  176.   iname.sin_port=htons(port);
  177.   if(bind(isock, &iname, (int) sizeof(iname)) == -1) 
  178.   { /* probable cause of error is that the port is in use */
  179.     error("binding socket");
  180.   }
  181.   
  182.   /* dup the newly-opened socket to stdin */
  183.   close(0);
  184.   dup(isock);
  185.  
  186. #ifdef TIOCNOTTY /* presumably BSD-like */
  187.   if((tty=open("/dev/tty", 0, 0)) != -1)
  188.   { ioctl(tty, TIOCNOTTY, (struct sgttyb *) 0);
  189.     (void) close(tty);
  190.   }
  191.   else
  192.   { if(setpgrp(0, 0)) 
  193.       error("setpgrp");
  194.   }
  195. #else /* presumably SYSV-like */
  196.   setpgrp();
  197. #endif
  198.  
  199.   for(i=1; i<10; i++)
  200.     (void) close(i);
  201.   
  202.   a = arglist;
  203.   *a++ = command;
  204.   if(timeout_arg)
  205.     *a++ = timeout_arg;
  206.   if(nice_arg)
  207.     *a++ = nice_arg;
  208.   *a++ = (char *) 0;
  209.   execvp(command, arglist);
  210.   exit(1); /* there's no good way to report errors here */
  211. }
  212.  
  213.  
  214. main(argc, argv)
  215.      int argc; char **argv;
  216. { char *s;
  217.  
  218.   me=argv[0];
  219.   for(;s = *++argv, --argc;)
  220.   { if(*s == '-')
  221.       switch(*++s)
  222.       {    
  223.       case 'k': /* kill */
  224.     kill_mode++;
  225.     break;
  226.       case 'q': /* query */
  227.       {    int rpid=ping(++s);
  228.     if(rpid) 
  229.     { printf("%d\n", rpid);
  230.       exit(0);
  231.     }
  232.     else exit(1);
  233.       }
  234.       case 'n': /* nice */
  235.     nice_arg= s-1; /* include the "-n" */
  236.     break;
  237.       case 't':
  238.     timeout_arg= s-1; /* include the "-t" */
  239.     break;
  240.       case 'p': /* port */
  241.     port=atoi(++s);
  242.     break;
  243.       default: 
  244.     goto usage;
  245.       }
  246.     else
  247.     { command= s;
  248.     }
  249.   }
  250.  
  251.   if(kill_mode) 
  252.     exit(murder());
  253.  
  254.   if(!command)
  255.     error("missing command");
  256.  
  257.   switch(fork())
  258.   { case -1:
  259.       error("fork");
  260.     case 0: /* child */
  261.       birth();
  262.     default: /* parent */
  263.       exit(0);
  264.   }
  265.  usage:
  266.   fprintf(stderr, "usage: %s [-k] [-q] [-nnice] [-ttimeout] [-pport]\n", me);
  267.   exit(1);
  268. }
  269.